package io.grpc.examples.helloworldtls;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.URL;

import io.grpc.Server;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyServerBuilder;
import io.grpc.stub.StreamObserver;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SMSslClientContextFactory;
import io.netty.handler.ssl.SMSslServerContextFactory;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;

public class HelloWorldGMServerTls {
	private Server server;

	private final String host;
	private final int port;
	private final String certChainFilePath;
	private final String privateKeyFilePath;
	private final String trustCertCollectionFilePath;

	public HelloWorldGMServerTls(String host, int port, String certChainFilePath, String privateKeyFilePath,
			String trustCertCollectionFilePath) {
		this.host = host;
		this.port = port;
		this.certChainFilePath = certChainFilePath;
		this.privateKeyFilePath = privateKeyFilePath;
		this.trustCertCollectionFilePath = trustCertCollectionFilePath;
	}

	private SslContext getSslContextBuilder() throws Exception {
//		SslContextBuilder sslClientContextBuilder = SslContextBuilder.forServer(new File(certChainFilePath),
//				new File(privateKeyFilePath));
//		if (trustCertCollectionFilePath != null) {
//			sslClientContextBuilder.trustManager(new File(trustCertCollectionFilePath));
//			sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE);
//		}
//		return GrpcSslContexts.configure(sslClientContextBuilder, SslProvider.OPENSSL).build();
		return build();
	}

	private static SslContext build() throws Exception {
//		String caCert = "E:\\develop\\workspace\\eclipse\\asgard\\grpc-tls-test\\src\\main\\resources\\gmssl-cert\\ca.crt";
//		String sslCert = "C:\\Users\\taifu\\Desktop\\临时\\grpc-cert\\gmssl-cert\\server.crt";
//		String sslKey = "C:\\Users\\taifu\\Desktop\\临时\\grpc-cert\\gmssl-cert\\server.pem";
//		String enCert = "C:\\Users\\taifu\\Desktop\\临时\\grpc-cert\\gmssl-cert\\server.crt";
//		String enKey = "C:\\Users\\taifu\\Desktop\\临时\\grpc-cert\\gmssl-cert\\server.pem";
//		InputStream caCertIn = new FileInputStream(caCert);
//		InputStream sslCertIn = new FileInputStream(sslCert);
//		InputStream sslKeyIn = new FileInputStream(sslKey);
//		InputStream enCertIn = new FileInputStream(enCert);
//		InputStream enKeyIn = new FileInputStream(enKey);
		

		InputStream caCertIn = HelloWorldGMServerTls.class.getClassLoader().getResourceAsStream("gmssl-cert/ca.crt");
		InputStream sslCertIn = HelloWorldGMServerTls.class.getClassLoader().getResourceAsStream("gmssl-cert/server.crt");
		InputStream sslKeyIn = HelloWorldGMServerTls.class.getClassLoader().getResourceAsStream("gmssl-cert/server.pem");
		InputStream enCertIn = HelloWorldGMServerTls.class.getClassLoader().getResourceAsStream("gmssl-cert/server.crt");
		InputStream enKeyIn = HelloWorldGMServerTls.class.getClassLoader().getResourceAsStream("gmssl-cert/server.pem");

		return SMSslServerContextFactory.build(caCertIn, sslCertIn, sslKeyIn, enCertIn, enKeyIn);
	}

	private void start() throws Exception {
		server = NettyServerBuilder.forAddress(new InetSocketAddress(host, port)).addService(new GreeterImpl())
				.sslContext(getSslContextBuilder()).build().start();
		System.out.println("Server started, listening on localhost " + port);
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				// Use stderr here since the logger may have been reset by its JVM shutdown
				// hook.
				System.err.println("*** shutting down gRPC server since JVM is shutting down");
				HelloWorldGMServerTls.this.stop();
				System.err.println("*** server shut down");
			}
		});
	}

	private void stop() {
		if (server != null) {
			server.shutdown();
		}
	}

	private void blockUntilShutdown() throws InterruptedException {
		if (server != null) {
			server.awaitTermination();
		}
	}

	public static void main(String[] args) throws Exception {
		args = new String[] { "localhost", "7401", "C:\\Users\\taifu\\Desktop\\临时\\grpc-cert\\gmssl-cert\\server.crt",
				"C:\\Users\\taifu\\Desktop\\临时\\grpc-cert\\gmssl-cert\\server.pem",
				"C:\\Users\\taifu\\Desktop\\临时\\grpc-cert\\gmssl-cert\\ca.crt" };

		if (args.length < 4 || args.length > 5) {
			System.out.println("USAGE: HelloWorldServerTls host port certChainFilePath privateKeyFilePath "
					+ "[trustCertCollectionFilePath]\n  Note: You only need to supply trustCertCollectionFilePath if you want "
					+ "to enable Mutual TLS.");
			System.exit(0);
		}

//        final HelloWorldServerTls server = new HelloWorldServerTls("localhost", 7443, args[2], args[3],
//                args.length == 5 ? args[4] : null);
		final HelloWorldGMServerTls server = new HelloWorldGMServerTls(args[0], Integer.parseInt(args[1]), args[2],
				args[3], args.length == 5 ? args[4] : null);
		server.start();
		server.blockUntilShutdown();
	}

	static class GreeterImpl extends GreeterGrpc.GreeterImplBase {

		@Override
		public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
			HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
			responseObserver.onNext(reply);
			responseObserver.onCompleted();
		}
	}
}